<?php

/**
 * 余外-湘免 SDK
 * @author chenyun
 */

namespace App\Service\VendorClient\Shopxiangmian;
use App\Model\PssModel\ServiceConfig;
use App\Service\Code\Normal;
use App\Service\TaskServer\TaskWorker;
use Service\AppService\IdService;
use Hyperf\Utils\WaitGroup;

class ShopxiangmianApiClient
{
    private $account  = 'shopxiangmian';
    protected $config;
    protected $RouteMap = [
        'createOrder'           => 'open/commitOrderInfo',
        'queryGoodsList'        => '/open/listGoodsByCate',
        'queryGoodsDetail'      => '/open/getGoodsInfo',
        'queryOrderExpress'     => 'merchant/customsStatus'
    ];
    /**
     * 初始参数
     * @param obj $collection
     */
    public function __construct( $apiBody = [] ) 
    {
        $this->config = $apiBody;
    }
    
    /**
     * 创建订单
     */
    public function createOrder( $params = [] ) 
    {   
        ini_set('serialize_precision', 16);
        
        if( empty($params['supplierOrder']) || empty($params['orderGoods']) || empty($params['order']) || empty($params['binfo']) ) {
            return Normal::returnCode(Normal::FAIL,"except param supplierOrder or orderGoods or order or binfo");
        }
        //组装订单参数
        $orderInfo = $params['supplierOrder'];
        $order     = $params['order'];
        $binfo     = $params['binfo'];
        //运费
        $deliver_money  = $orderInfo['deliver_money'];
        //商品下单组
        $orderGoodsList = [];
        $productAmt = $TaxAmt = 0 ;
        foreach ($params['orderGoods'] as $key => $item ) 
        {
            //卖价
            $price              = $item['price'];
            //商品购买规格数量
            $spec_num           = $item['spec_num'];
            //商品购买数量(下单数量 X 起售数量)
            $quantity           = $item['quantity'];
            //实际购买数量
            $buyAcount          = $spec_num * $quantity ;
            //单个商品价格
            $singleGoodsPrice   = bcdiv((string)$price, (string)$spec_num,3);
            $singleGoodsPrice   = ceil(bcmul((string)$singleGoodsPrice,(string)'100',1));
            $singleGoodsPrice   = bcdiv((string)$singleGoodsPrice,'100',2);
            
            //单个商品总不含税价格
            $totalGoods         = bcmul((string)$singleGoodsPrice,(string)$buyAcount,2);
            
            //商品组
            $orderGoodsList[] = [
                "goodsid"            => $item['supplier_skucode'],
                "total"       => $buyAcount,
                "price"        => $singleGoodsPrice,
                "goodssn"   => $totalGoods,
                "productsn"     => 0,
            ];
            $productAmt = bcadd((string)$productAmt,(string)$totalGoods,2);
        }
        

        //实际下单金额 
        $real_total_money = $orderInfo['real_total_money'];
        
        //订单总金额 = 不含税商品总金额 + 总税费 + 运费 - 优惠金额
        $ActualPaidAmt = bcadd((string)$productAmt,(string)$TaxAmt,2);
        $ActualPaidAmt = bcadd((string)$ActualPaidAmt,(string)$deliver_money,2);
        
        //优惠金额
        $discount_money = bcsub((string)$ActualPaidAmt,$real_total_money,2);
        
        //下单支付的时候支付信息
        $apply_extends  = @json_decode($orderInfo['apply_extends'],true);
        
        $payTime        = empty($order['payTime']) ? $orderInfo['pay_time'] :$order['payTime'];
        //支付时间
        $pay_time       = $payTime ? $payTime : time();
        $pay_time       = date('Y-m-d H:i:s',$payTime);
        
        //支付流水号
        $pay_sn         = $order['paySerial']??$orderInfo['pay_sn'];
        
        //获取上游供应商支付方式路由
        $payCommanyCode = $apply_extends['payCommanyCode'] ?? '';
        $PayCompanyCode = $order['payCommanyCode'] ? $order['payCommanyCode'] : $payCommanyCode;
        $pay_value      = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_PAY, $PayCompanyCode);
        if (empty($pay_value)) {
            return Normal::returnCode(Normal::FAIL, "支付公司编码：【{$PayCompanyCode}】未映射，请联系管理员处理");
        } 
        
        //电商平台信息
        $enterpriseNum  = $apply_extends['enterpriseNum'] ?? '';
        $enterpriseName = $apply_extends['enterpriseName'] ?? '';
        $enterpriseNum  = $order['enterpriseNum'] ? $order['enterpriseNum'] : $enterpriseNum;
        $enterpriseName = $order['enterpriseName'] ? $order['enterpriseName'] : $enterpriseName;
        
        //获取电商平台映射配置
        /* $channel_value = ServiceConfig::instance()->getConfigByEventsValue($this->account, ServiceConfig::TYPE_CHANNEL, $enterpriseNum);
        if( empty($channel_value) ) {
            return Normal::returnCode(Normal::FAIL,"支付电商平台编码：【{$enterpriseNum}】未映射，请联系管理员处理");
        } */
        
        //创建订单数据
        $order = [
            'OriginOrderNo'         => $orderInfo['supplier_dsn'],
            'SaleOrderTime'         => date("Y-m-d H:i:s",time()),
            'SalesOrderType'        => 1,
            'InvoicingCurrency'     => "CNY",
            'AcceptedExRate'        => 1,
            'PaymentTime'           => $pay_time,
            'OrderSource'           => 'other',
            'PaymentStatus'         => 1,
            'PaymentType'           => $pay_value,
            'SaleOrderPaymentNo'    => $pay_sn,
            'ShopNo'                => $this->config["ShopNo"],
            'ConsigneeCountry'      => "中国",
            'ConsigneeProvince'     => $orderInfo['province'],
            'ConsigneeCity'         => $orderInfo['city'],
            'ConsigneeDistrict'     => $orderInfo['district'],
            'ConsigneeStreetLine'   => $orderInfo['receive_address'],
            'Consignee'             => $orderInfo['receive_name'],
            'ConsigneePhone'        => $orderInfo['recveive_phone'],
            'BuyerName'             => $orderInfo['buyer_realname'],
            'BuyerIdNumber'         => $orderInfo['buyer_idcard']
        ];

        $address =[
            'payName'       => $orderInfo['buyer_realname'],
            'idCard'        => $orderInfo['buyer_idcard'],
            'acceptName'    => $orderInfo['receive_name'],
            'mobile'        => $orderInfo['recveive_phone'],
            'province'      => $orderInfo['pr
                
        ovince'],
            'city'          => $orderInfo['city'],
            'county'        => $orderInfo['district'],
            'address'       => $orderInfo['receive_address'],
            'street'        => '',
        ];
        $orderAddParam = [
            'price'         => $ActualPaidAmt,
            'goodsprice'    => $real_total_money,
            'paytype'       => $pay_value,
            'remark'        => $orderInfo['order_remark'],
            'dispatchprice' => $deliver_money,
            'address'       => $address,
            'orderGoodsList'=> $orderGoodsList,
        ];
        $data = [
            'orderAddParam'     => $orderAddParam,
        ];
        
        $requestParam = [
            'method'    => 'createOrder',
            'data'      => $data
        ];
        $res = $this->execute($requestParam);
        return $res;
    }
   
    /**
     * 获取取消订单
     */
    public function cancelOrder( $params = [] ) 
    {
        return Normal::returnCode(Normal::SUC,"处理成功");
    }
    /**
     * 查询物流单信息
     * @param array $param
     */
    public function queryOrderExpress( $param = [] )
    {
        $data = [
            'ErpCodes'  => [
                [
                    'SalesCode'    => $param['thirdpart_order_sn']
                ]
            ]
        ];
        $requestParam = [
            'method'    => 'queryOrderExpress',
            'data'      => $data
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 查询商品列表
     */ 
    public function queryGoodsList($params = [])
    {
        $data = [
            'pageNum'   => $params["page"]??0,
            'pageSize'  => 50,
            'categoryId'=>0,
        ];
        $requestParam = [
            'method'    => 'queryGoodsList',
            'data'      => $data,
        ];
        $res  = $this->getExecute($requestParam);
        if($res["code"] != Normal::SUC ){
            return $res;
        }
        $result_query_goods = $res["data"]["data"]["list"];
        $details    = [];
        $size       = $this->config['limit'] ?? 10;
        $chunkArr   = array_chunk($result_query_goods,$size);
        foreach ($chunkArr as $skuNos)
        {
            $wg = new WaitGroup();
            $count = count($skuNos);
            $wg->add($count);
            foreach ($skuNos as $sku)
            {
                co(function () use ($wg,$sku, & $details)
                {
                    $data = [
                        'goodsid' => $sku["id"],
                    ];
                    $requestParam = [
                        'method'    => 'queryGoodsDetail',
                        'data'      => $data,
                    ];
                    $responseParam = $this->getExecute($requestParam);
                    if ($responseParam['code']== Normal::SUC && isset($responseParam['data']['data'])){
                        $details[]=$responseParam['data']["data"];
                    }
                    $wg->done();
                });
            }
            $wg->wait();
        }
        return Normal::returnCode(Normal::SUC,"请求成功",$details);
    }

    /**
     * 随机32位字符串
     */
    function randstrpay($length=32) {
        $rand='';
        $randstr= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $max = strlen($randstr)-1;
        mt_srand((double)microtime()*1000000);
        for($i=0;$i<$length;$i++) {
            $rand.=$randstr[mt_rand(0,$max)];
        }
        return $rand;
    }
    /**
     * 加签
     * @param array $param
     */
    protected function getSign( $params = [] ,$timestamp,$nonce)
    {
        $string = "";
        //第一步：排升序
        ksort($params);
        //第二步：组装参数,格式为key=>value
        foreach($params as $key =>$value){
            $string .= $key."=".$value."&";
        }
        $string = substr($string, 0,-1);
        //第三步：拼接字符串
        $md5string = $this->config["appId"]."&".$this->config["appSecret"]."&".$nonce."&".$timestamp;
        if($string){
            $md5string .= "&".$string;
        }
        //第四步：md5
        $md5string = md5($md5string);
        //第五步：md5转大写
        return strtoupper($md5string);
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function getExecute( $param = [] )
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        } 
        $method     = $param['method'];
        $timestamp  = time();
        $nonce      = $this->randstrpay();
        $sign       = $this->getSign($param["data"],$timestamp,$nonce);
        $baseurl    = $this->config["baseurl"].$this->RouteMap[$method].'?'.http_build_query($param["data"]);
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method,
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $baseurl,
                'data'      => '',
                'method'    => 'get',
                'format'    => '',
                'header'    => [
                    "appId: {$this->config["appId"]}",
                    "nonce: {$nonce}",
                    "timestamp: {$timestamp}",
                    "sign: {$sign}",
                ],

            ],
        ];
        $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = json_decode($res,true);
        if( isset($resHttp['code']) && $resHttp['code'] == 200 ) {
            return Normal::returnCode(Normal::SUC,"请求成功",$resHttp);
        }

        $message = isset($resHttp['message']) ? $resHttp['message'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute( $param = [] )
    {
        if( empty($param['data']) ) {
            return Normal::returnCode(Normal::FAIL,"数据不能为空");
        }
        $method     = $param['method'];
        $baseurl    = $this->config["baseurl"].$this->RouteMap[$method];
        $timestamp  = time();
        $nonce      = $this->randstrpay();
        $param["data"]["sign"] = $this->getSign($param["data"],$timestamp,$nonce);
        $parameter = [
            [
                'tag'       => $this->account.'_'.$method, 
                'uid'       => IdService::instance()->getOtherID(),
                'url'       => $baseurl,
                'data'      => $param['data'],
                'method'    => 'post',
                'format'    => 'json',
                'header'    => ["Content-Type: application/json; charset=utf-8"],
    
            ],
        ];
        if( in_array($method,['queryGoods','queryGoodsDetail']) ) {
            $resTask = TaskWorker::instance()->addTask($parameter,'handleDiableTask');
        } else {
            $resTask = TaskWorker::instance()->addTask($parameter);
        }
        $resTask = current($resTask);
        $res     = $resTask['response']['result'];
        $resHttp = json_decode($res,true);
        if( isset($resHttp['Success']) && $resHttp['Success'] == 1 ) {
            return Normal::returnCode(Normal::SUC,"操作成功",$resHttp["data"]);
        }
    
        $message = isset($resHttp['message']) ? $resHttp['message'] : '请求失败';
        return Normal::returnCode(Normal::FAIL,$message);
    }
}